package com.jlb.jolokia.example.restrictor;

import java.util.ArrayList;
import java.util.List;

import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;

import org.jolokia.restrictor.Restrictor;
import org.jolokia.util.HttpMethod;
import org.jolokia.util.RequestType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Sample Jolokia {@link Restrictor} implementation used to allow only specific
 * JMX MBeans and operations. The example currently permits
 * <strong>only</strong> the following:
 * <ol>
 * <li>HTTP GET requests
 * <li>EXEC Jolokia Operation
 * <li>MBean Apache Camel timer-route1 - start(), stop(), suspend()
 * <li>MBean Apache Camel timer-route1 - stop()
 * </ol>
 * 
 * All other operations are explicitly denied.
 * 
 * @author Justin Braathen
 * 
 */
public class JolokiaRestrictor implements Restrictor {
	private static final Logger LOG = LoggerFactory
			.getLogger(JolokiaRestrictor.class);

	private static final List<JolokiaOperation> ALLOWED_OPERATIONS = new ArrayList<JolokiaOperation>();

	/**
	 * ************************************************************************
	 * Note: The static initializer is for illustrative purposes only. Ideally
	 * this would be abstracted via an environmentalized property framework.
	 * ************************************************************************
	 */
	static {
		try {
			ALLOWED_OPERATIONS
					.add(new JolokiaOperation(
							"org.apache.camel:context=camel-context-id,type=routes,name=\"timer-route1-id\"",
							"start()", "stop()", "suspend()"));

			ALLOWED_OPERATIONS
					.add(new JolokiaOperation(
							"org.apache.camel:context=camel-context-id,type=routes,name=\"timer-route2-id\"",
							"stop()"));

		} catch (MalformedObjectNameException e) {
			LOG.error("#JolokiaRestrictor static initializer", e);
		}
	}

	/**
	 * Allow only HTTP GET requests.
	 */
	@Override
	public boolean isHttpMethodAllowed(HttpMethod pMethod) {
		return pMethod.equals(HttpMethod.GET);
	}

	/**
	 * Allow only Jolokia {@link RequestType#EXEC}
	 */
	@Override
	public boolean isTypeAllowed(RequestType pType) {
		return pType.equals(RequestType.EXEC);
	}

	/**
	 * @see Restrictor#isAttributeReadAllowed(ObjectName, String)
	 */
	@Override
	public boolean isAttributeReadAllowed(ObjectName pName, String pAttribute) {
		LOG.info("\n#isAttributeReadAllowed: name: {} attribute: {}\n", pName,
				pAttribute);
		return true;
	}

	/**
	 * @see Restrictor#isAttributeWriteAllowed(ObjectName, String)
	 */
	@Override
	public boolean isAttributeWriteAllowed(ObjectName pName, String pAttribute) {
		LOG.info("\n#isAttributeWriteAllowed: name: {} attribute: {}\n", pName,
				pAttribute);
		return true;
	}

	/**
	 * Allows only {@link JolokiaOperation} (MBean/Operations) specified in the
	 * ALLOWED_OPERATIONS {@link List}
	 * 
	 * @see Restrictor#isOperationAllowed(ObjectName, String)
	 */
	@Override
	public boolean isOperationAllowed(ObjectName pName, String pOperation) {

		LOG.info("\n#isOperationAllowed: name: {}\n", pName);

		for (JolokiaOperation operation : ALLOWED_OPERATIONS) {
			if (operation.isAllowed(pName, pOperation)) {
				return true;
			}
		}

		return false;
	}

	/**
	 * @see Restrictor#isRemoteAccessAllowed(String...)
	 */
	@Override
	public boolean isRemoteAccessAllowed(String... pHostOrAddress) {
		for (String host : pHostOrAddress) {
			LOG.info("\n#isRemoteAccessAllowed: host: {}\n", host);
		}
		return true;
	}

	/**
	 * @see Restrictor#isOriginAllowed(String, boolean)
	 */
	@Override
	public boolean isOriginAllowed(String pOrigin, boolean pIsStrictCheck) {
		LOG.info("\n#isOriginAllowed: origin: {} isStrictCheck: {}\n", pOrigin,
				pIsStrictCheck);
		return true;
	}

}
